#!/usr/bin/env bash

set -eo pipefail

DIR="$(dirname "${BASH_SOURCE[0]}")"

source "$DIR/lib/helpers.bash"

go run ./build/*.go build

export GO_FILECOIN_LOG_LEVEL=3
export FILECOIN_PROOFS_FAST_DELAY_SECONDS=1
AUTO_SEAL_INTERVAL_SECONDS="0"

if [[ "$1" = "test" ]]; then
    echo "Running Retrieval Test Against Test Devnet"
    CLUSTER="test"
    FAUCET_ADDR="http://test.kittyhawk.wtf:9797/tap"
elif [[ "$1" = "nightly" ]]; then
    echo "Running Retrieval Test Against Nightly Devnet"
    CLUSTER="nightly"
    FAUCET_ADDR="http://nightly.kittyhawk.wtf:9797/tap"
else
    echo "must provide first argument of either 'test' or 'nightly' for desired devnet"
    exit 1
fi

if [[ -z "$2" ]]; then
    USE_SMALL_SECTORS="true"
else
    USE_SMALL_SECTORS="$2"
fi

export FIL_USE_SMALL_SECTORS=${USE_SMALL_SECTORS}

# forward-declare stuff that we need to clean up
MN_PID=""
CL_PID=""
MN_REPO_DIR=""
CL_REPO_DIR=""
PIECE_1_PATH=$(mktemp)
PIECE_2_PATH=$(mktemp)
UNSEAL_PATH=$(mktemp)
BLOCK_TIME="5s"
HODL="HODL HODL HODL HODL HODL HODL HODL HODL HODL HODL HODL HODL HODL HODL HODL"

if [ "${USE_SMALL_SECTORS}" = true ] ; then
    echo "${HODL}" > "${PIECE_1_PATH}"
    echo "BLOCKCHAIN BLOCKCHAIN BLOCKCHAIN BLOCKCHAIN BLOCKCHAIN BLOCKCHAIN BLOCKCHAIN" > "${PIECE_2_PATH}"
else
    # Keeping first piece block count at: 1040000 < 1040384 = 1065353216/1024
    # will prevent first piece from triggering seal.
    dd if=/dev/urandom of="${PIECE_2_PATH}" bs=1024 count=1040000
    # A total block count of: (piece_1_count + piece_2_count) = 1040000 + 500 = 1040500 > 1040384
    # will cause the second piece to trigger a seal.
    dd if=/dev/urandom of="${PIECE_1_PATH}" bs=1024 count=500
fi

trap finish EXIT

MN_REPO_DIR=$(mktemp -d)
MN_CMDAPI_PORT=$(free_port)
MN_SWARM_PORT=$(free_port)

CL_REPO_DIR=$(mktemp -d)
CL_CMDAPI_PORT=$(free_port)
CL_SWARM_PORT=$(free_port)

echo ""
echo "initializing daemons..."
init_devnet_daemon "${MN_REPO_DIR}" "${MN_CMDAPI_PORT}"
init_devnet_daemon "${CL_REPO_DIR}" "${CL_CMDAPI_PORT}"

echo ""
echo "start daemons..."
start_daemon "${MN_REPO_DIR}" "${MN_CMDAPI_PORT}" "${MN_SWARM_PORT}"
MN_PID=$!
start_daemon "${CL_REPO_DIR}" "${CL_CMDAPI_PORT}" "${CL_SWARM_PORT}"
CL_PID=$!

sleep 2

echo ""
echo "get default wallet addresses..."
MN_MINER_OWNER_FIL_ADDR=$(./go-filecoin wallet addrs ls --repodir="${MN_REPO_DIR}")

echo ""
echo "connecting to ${CLUSTER} devnet..."
wait_for_peers "${MN_REPO_DIR}"
wait_for_peers "${CL_REPO_DIR}"

echo ""
echo "hitting the faucet to give the miner owner some \$FIL..."
FAUCET_MESSAGE_CID=$(curl -X POST -F "target=${MN_MINER_OWNER_FIL_ADDR}" "${FAUCET_ADDR}" | cut -d' ' -f 4)

echo ""
echo "wait for faucet message..."
./go-filecoin message wait "${FAUCET_MESSAGE_CID}" --repodir="${MN_REPO_DIR}"
./go-filecoin message wait "${FAUCET_MESSAGE_CID}" --repodir="${CL_REPO_DIR}"

echo ""
echo "creating miner for mining node..."
MN_MINER_FIL_ADDR=$(./go-filecoin miner create 10 100 --repodir="${MN_REPO_DIR}")

echo ""
echo "get mining node's libp2p identity..."
MN_PEER_ID=$(get_peer_id "${MN_REPO_DIR}")

echo ""
echo "update miner's libp2p identity to match its node's..."
MINER_UPDATE_PID_MSG_CID=$(miner_update_pid "${MN_MINER_FIL_ADDR}" "${MN_PEER_ID}" "${MN_REPO_DIR}")

MINER_ADD_ASK_MSG_CID=$(add_ask "${MN_MINER_FIL_ADDR}" 10 10000 "${MN_REPO_DIR}")

echo ""
echo ""
echo ""
echo "********************** BEGIN STORAGE PROTOCOL"
echo ""
echo ""
echo ""

echo ""
echo "miner node starts mining..."
./go-filecoin mining start \
  --repodir="$MN_REPO_DIR"

echo ""
echo "Waiting until messages are in blockchain..."
fork_message_wait 104 "${MINER_UPDATE_PID_MSG_CID}" "${MN_REPO_DIR}"
fork_message_wait 105 "${MINER_UPDATE_PID_MSG_CID}" "${CL_REPO_DIR}"
fork_message_wait 106 "${MINER_ADD_ASK_MSG_CID}" "${MN_REPO_DIR}"
fork_message_wait 107 "${MINER_ADD_ASK_MSG_CID}" "${CL_REPO_DIR}"

echo ""
echo "block until miner peer id-update message appears in chains..."
join 104
join 105
join 106
join 107

echo ""
echo "client imports piece 1..."
PIECE_1_CID=$(./go-filecoin client import --repodir="${CL_REPO_DIR}" < "${PIECE_1_PATH}")

echo ""
echo "client proposes a storage deal, which transfers file 1..."
./go-filecoin client propose-storage-deal "${MN_MINER_FIL_ADDR}" "${PIECE_1_CID}" 0 5 \
  --repodir="$CL_REPO_DIR" \

echo ""
echo "client imports piece 2..."
PIECE_2_CID=$(./go-filecoin client import --repodir="${CL_REPO_DIR}" < "${PIECE_2_PATH}")

echo ""
echo "client proposes a storage deal, which transfers piece 2 (triggers seal)..."
./go-filecoin client propose-storage-deal "${MN_MINER_FIL_ADDR}" "${PIECE_2_CID}" 0 5 \
  --repodir="$CL_REPO_DIR" \

echo ""
echo "wait for commitSector sent by miner owner to be included in a block viewable by both nodes..."
wait_for_message_in_chain_by_method_and_sender commitSector "${MN_MINER_OWNER_FIL_ADDR}" "${CL_REPO_DIR}"

wait_for_message_in_chain_by_method_and_sender commitSector "${MN_MINER_OWNER_FIL_ADDR}" "${MN_REPO_DIR}"
echo ""
echo ""
echo ""
echo "********************** BEGIN RETRIEVAL PROTOCOL"
echo ""
echo ""
echo ""

./go-filecoin retrieval-client retrieve-piece "${MN_MINER_FIL_ADDR}" "${PIECE_1_CID}" \
  --repodir="${CL_REPO_DIR}" > "${UNSEAL_PATH}"


GOT=$(shasum < "${UNSEAL_PATH}")
EXPECTED=$(shasum < "${PIECE_1_PATH}")

if [ "${GOT}" = "${EXPECTED}" ]; then
    echo "Round trip passed!"
    exit 0
else
    echo "Round trip Failed!, expected file"
    echo "${UNSEAL_PATH}"
    echo "to have same contents as file"
    echo "${PIECE_1_PATH}"
    exit 1
fi
